home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -seriously_amiga- / shareware / programming / c / amivogl-mdev / drivers / next.c < prev    next >
Text File  |  1998-01-12  |  11KB  |  572 lines

  1. /*
  2.  * VOGL/VOGLE driver for NeXTStep.
  3.  * shamelessly hacked from X11 driver 9/91 by
  4.  *
  5.  * Patrick J. Flynn
  6.  * School of EECS
  7.  * Washington State University
  8.  * Pullman, WA 99164-2752 USA cha cha cha
  9.  * flynn@eecs.wsu.edu
  10.  *
  11.  * modified 9/22/91 to use NeXToid defaults (owner: "VOGL") for
  12.  *
  13.  * + preferred small & large font names/styles/sizes:
  14.  *    `SmallFont' `LargeFont'
  15.  *
  16.  *   If no defaults are present, SmallFont is "Ohlfs 9.0" and
  17.  *                               LargeFont is "Ohlfs 18.0"
  18.  *
  19.  *   The space in the font string is significant (see NeXT_font below)
  20.  *
  21.  * + window size & placement: `WindowX' `WindowY'
  22.  *                            `WindowW' `WindowH'
  23.  * 
  24.  * If no defaults are present, the window is anchored (LL) at (10,10)
  25.  * and is 792 pixels wide & high.  If the user has set the preferred
  26.  * position & size using the VOGL prefXXX() calls, they override the
  27.  * defaults.
  28.  *
  29.  * THIS CODE HAS ONLY BEEN TESTED ON A DOUBLE-HEADED CUBE (2 bit + ND)
  30.  * There are a couple of color-screen-centrisms and 24-bit-centrisms in
  31.  * the code, but NextStep is pretty good about drawing as good as it
  32.  * can on the available hardware.
  33.  *
  34.  */
  35.  
  36. /*
  37.  * set VOGLE if this is really for the VOGLE library.
  38. #define VOGLE 1
  39.  */
  40.  
  41. #include <stdio.h>
  42. #include <math.h>
  43. #include <strings.h> /* strfoo() */
  44.  
  45. #ifdef VOGLE
  46. #include "vogle.h"
  47. #else
  48. #include "vogl.h"
  49. #endif
  50.  
  51. #import <appkit/Application.h> /* [NXApp colorScreen] */
  52. #import <appkit/Window.h>
  53. #import <appkit/View.h>
  54. #import <appkit/Font.h>
  55. #import <dpsclient/wraps.h>
  56. #import <dpsclient/event.h>
  57. #import <appkit/color.h>
  58. #import <appkit/graphics.h>
  59. #import <appkit/nextstd.h>
  60. #import <appkit/NXImage.h>     /* double buffer */
  61. #import <appkit/afm.h>         /* hack to get metrics */
  62. #import <appkit/defaults.h>
  63.  
  64. #define    CMAPSIZE    4096   /* perhaps we'll go RGBmode someday. */
  65.  
  66. Window *winder;
  67. View *view;
  68. Font *phont;
  69. NXFontMetrics *fm;
  70. NXImage *backbuf = nil;
  71. NXColor colormap[CMAPSIZE]; /* yeah, I know it's ugly. */
  72. int back_used;
  73.  
  74. id drawable; /* the thing we're drawing in (a View or an NXImage) */
  75.  
  76. /*
  77.  * NeXT_init()
  78.  * initializes the NeXT display.
  79.  */
  80. int NeXT_init(void)
  81. {
  82.   int x0,y0,xs,ys;
  83.   NXRect r;
  84.   char name[80];
  85.   const char *ptr;
  86.  
  87.   NXApp = [Application new];
  88.   getprefposandsize(&x0,&y0,&xs,&ys);
  89.  
  90.   if (x0<0) {
  91. #ifdef VOGLE
  92.     ptr=NXReadDefault("VOGLE","WindowX");
  93. #else
  94.     ptr=NXReadDefault("VOGL","WindowX");
  95. #endif
  96.     if (!ptr)
  97.       x0=10;
  98.     else
  99.       if (sscanf(ptr,"%d",&x0) != 1) x0=10;
  100.     };
  101.  
  102.   if (y0<0) {
  103. #ifdef VOGLE
  104.     ptr=NXReadDefault("VOGLE","WindowY");
  105. #else
  106.     ptr=NXReadDefault("VOGL","WindowY");
  107. #endif
  108.     if (!ptr)
  109.       y0=10;
  110.     else 
  111.       if (sscanf(ptr,"%d",&y0) != 1) y0=10;
  112.     };
  113.   
  114.   if (xs<0) {
  115. #ifdef VOGLE
  116.     ptr=NXReadDefault("VOGLE","WindowW");
  117. #else
  118.     ptr=NXReadDefault("VOGL","WindowW");
  119. #endif
  120.     if (!ptr)
  121.       xs=792;
  122.     else
  123.       if (sscanf(ptr,"%d",&xs) != 1) xs=792;
  124.     };
  125.   
  126.   if (ys<0) {
  127. #ifdef VOGLE
  128.     ptr=NXReadDefault("VOGLE","WindowH");
  129. #else
  130.     ptr=NXReadDefault("VOGL","WindowH");
  131. #endif
  132.     if (!ptr)
  133.       ys=792;
  134.     else
  135.       if (sscanf(ptr,"%d",&ys) != 1) ys=792;
  136.     };
  137.   
  138.   NXSetRect(&r,x0,y0,xs,ys);
  139.   winder = [[Window alloc] initContent:&r
  140.                                  style:NX_TITLEDSTYLE
  141.                                backing:NX_RETAINED
  142.                             buttonMask:0
  143.                                  defer:NO
  144.                                 screen:[NXApp colorScreen]];
  145.   [winder setDepthLimit:NX_TwentyFourBitRGBDepth];
  146.   vdevice.depth = 24;
  147.   colormap[0]=NX_COLORBLACK;
  148.   colormap[1]=NX_COLORRED;
  149.   colormap[2]=NX_COLORGREEN;
  150.   colormap[3]=NX_COLORYELLOW;
  151.   colormap[4]=NX_COLORBLUE;
  152.   colormap[5]=NX_COLORMAGENTA;
  153.   colormap[6]=NX_COLORCYAN;
  154.   colormap[7]=NX_COLORWHITE;
  155.  
  156. #ifdef VOGLE
  157.     sprintf(name, "vogle %d", getpid());
  158.     [winder setTitle:name];
  159. #else
  160.   if (!vdevice.wintitle) {
  161.     sprintf(name, "vogl %d", getpid());
  162.     [winder setTitle:name];
  163.     }
  164.   else {
  165.     [winder setTitle:vdevice.wintitle];
  166.     };
  167. #endif
  168.  
  169.   drawable = view = [winder contentView];
  170.  
  171.   phont = nil;
  172.  
  173.   vdevice.sizeX = vdevice.sizeY = MIN(xs,ys) - 1;
  174.   vdevice.sizeSx = xs;
  175.   vdevice.sizeSy = ys;
  176.   back_used = 0;
  177.   [[winder makeKeyAndOrderFront:0] display];
  178.   [drawable lockFocus];
  179.   return(1);
  180. }
  181.  
  182. /*
  183.  * NeXT_exit
  184.  *
  185.  *    cleans up before returning the window to normal.
  186.  */
  187. int NeXT_exit(void)
  188. {
  189.   [winder free];
  190.   if (backbuf) [backbuf free];
  191.   [NXApp free];
  192.   return(1);
  193. }
  194.  
  195. /*
  196.  * NeXT_draw
  197.  *
  198.  *    draws a line from the current graphics position to (x, y).
  199.  *
  200.  */
  201. int NeXT_draw(
  202.   int x,
  203.   int y)
  204. {
  205.   PSsetlinewidth(0.0);
  206.   PSnewpath();
  207.   PSmoveto(vdevice.cpVx,vdevice.cpVy);
  208.   PSlineto(x,y);
  209.   PSstroke();
  210.   if (vdevice.sync)
  211.       NXPing();
  212. }
  213.  
  214. /*
  215.  * NeXT_getkey
  216.  *
  217.  *    grab a character from the keyboard - blocks until one is there.
  218.  */
  219. int NeXT_getkey(void)
  220. {
  221.   NXEvent e;
  222.   NXEvent *ee = NXGetOrPeekEvent(DPSGetCurrentContext(),&e,
  223.                                  NX_KEYDOWNMASK,NX_FOREVER,NX_BASETHRESHOLD,0);
  224.   if (ee == NULL) fprintf(stderr,"error: NeXT_getKey failed.\n");
  225.   return ee->data.key.charCode;
  226. }
  227.  
  228. /*
  229.  * NeXT_checkkey
  230.  *
  231.  *    Check if there has been a keyboard key pressed.
  232.  *    and return it if so.
  233.  */
  234. int NeXT_checkkey(void)
  235. {
  236.   NXEvent e;
  237.   NXEvent *ee = NXGetOrPeekEvent(DPSGetCurrentContext(),&e,
  238.                                  NX_KEYDOWNMASK,0.0,NX_BASETHRESHOLD,0);
  239.   if (ee == NULL) return 0;
  240.   return ee->data.key.charCode;
  241. }
  242.  
  243. /*
  244.  * NeXT_locator
  245.  *
  246.  * return the window location of the cursor, plus which mouse button,
  247.  * if any, is been pressed.
  248.  * 
  249.  * the right mouse button is the LSB.  There is no middle button on a NeXT
  250.  * so the 2LSB is always 0.  The left mouse button is the 3LSB.
  251.  */
  252. int NeXT_locator(
  253.   int *wx,
  254.   int *wy)
  255. {
  256.   int msk=0,flg;
  257.   NXPoint p;
  258.   [winder getMouseLocation:&p];
  259.   [view convertPoint:&p fromView:nil];
  260.   *wx = p.x;
  261.   *wy = p.y;
  262.   PSbuttondown(&flg);
  263.   if (flg) msk=4;
  264.   PSrightbuttondown(&flg);
  265.   if (flg) msk+=1;
  266.   return msk;
  267. }
  268.  
  269. #ifdef VOGLE
  270. /*
  271.  * NeXT_clear
  272.  *
  273.  * Clear the screen (or current buffer )to current colour
  274.  */
  275. int NeXT_clear(void)
  276. {
  277.   NXRect r;
  278.   [view getBounds:&r];
  279.   NXRectFill(&r);
  280.   if (vdevice.sync)
  281.       NXPing();
  282. }
  283.  
  284. #else
  285.  
  286. /*
  287.  * NeXT_clear
  288.  *
  289.  * Clear the viewport (or current buffer )to current colour
  290.  */
  291. int NeXT_clear(void)
  292. {
  293.   NXRect r;
  294.   float w=vdevice.maxVx - vdevice.minVx;
  295.   float h=vdevice.maxVy - vdevice.minVy;
  296.   NXSetRect(&r,vdevice.minVx,vdevice.minVy,w,h);
  297.   [view getBounds:&r];
  298.   NXRectFill(&r);
  299.   if (vdevice.sync)
  300.       NXPing();
  301. }
  302.  
  303. #endif
  304.  
  305. /*
  306.  * NeXT_color
  307.  *
  308.  *    set the current drawing color index.
  309.  */
  310. int NeXT_color(int ind)
  311. {
  312.   NXSetColor(colormap[ind]);
  313. }
  314.  
  315. /*
  316.  * NeXT_mapcolor
  317.  *
  318.  *    change index i in the color map to the appropriate r, g, b, value.
  319.  */
  320. int NeXT_mapcolor(
  321.   int i,
  322.   int r,
  323.   int g,
  324.   int b)
  325. {
  326.   if (i >= CMAPSIZE) return(-1);
  327.   colormap[i]=NXConvertRGBToColor(1.0*r/255.0,1.0*g/255.0,1.0*b/255.0);
  328. }
  329.  
  330. /*
  331.  * NeXT_font
  332.  *
  333.  *   Set up a hardware font. Return 1 on success 0 otherwise.
  334.  *
  335.  * This is system-dependent.  I assume that the fontfile parameter
  336.  * has the font family name followed by a blank, followed by the size 
  337.  * in points, e.g. "Ohlfs 384.7", "Helvetica-BoldOblique 1.0".
  338.  * Note that the size can be floating-point.
  339.  *
  340.  */
  341. /* c:  ugly blech yech
  342.  */
  343. char *strdup(const char *c)
  344. {
  345.   char *d=malloc(1+strlen(c));
  346.   bcopy(c,d,1+strlen(c));
  347.   return d;
  348. }
  349.  
  350. /* input: NS = "Name size", i.e. "Ohlfs 32.9".
  351.  * output: *s = 32.9, return value = "Ohlfs";
  352.  * returns NULL if string doesn't have both name and size.
  353.  */
  354. char *_getFontNameNSize(
  355.   const char *ns,
  356.   float *s)
  357. {
  358.   char *p,*q;
  359.   if (!ns) return 0;
  360.   p=strdup(ns); /* barf */
  361.   q=index(p,' ');
  362.   if (!q) return 0;
  363.   *q++ = '\0'; /* null-terminate name */
  364.   if (sscanf(q,"%f",s) != 1) { free(p); return 0;};
  365.   return p;
  366. }
  367.   
  368.   
  369. int NeXT_font(char *fontfile)
  370. {
  371.   char *name;
  372.   float size;
  373.   Font *newfont;
  374.   if (!strcmp(fontfile,"small")) {
  375. #ifdef VOGLE
  376.     name=_getFontNameNSize(NXReadDefault("VOGLE","SmallFont"),&size);
  377. #else
  378.     name=_getFontNameNSize(NXReadDefault("VOGL","SmallFont"),&size);
  379. #endif
  380.     if (!name) { name=strdup("Ohlfs"); size=9.0; };
  381.     }
  382.   else if (!strcmp(fontfile,"large")) {
  383. #ifdef VOGLE
  384.     name=_getFontNameNSize(NXReadDefault("VOGLE","LargeFont"),&size);
  385. #else
  386.     name=_getFontNameNSize(NXReadDefault("VOGL","LargeFont"),&size);
  387. #endif
  388.     if (!name) { name=strdup("Ohlfs"); size=18.0; };
  389.     }
  390.   else {
  391.     name=_getFontNameNSize((const char *)fontfile,&size);
  392.     if (!name) { name=strdup("Ohlfs"); size=9.0; };
  393.     };
  394.   newfont = [Font newFont:name size:size matrix:NX_IDENTITYMATRIX];
  395.   free(name);
  396.   if (newfont) {
  397.     NXFontMetrics *fm = [newfont metrics];
  398.     int i;
  399.     float wmax=0.0;
  400.     [phont free];
  401.     phont = newfont;
  402.     [phont set];
  403.  
  404.     /* set hheight and hwidth for hardware fonts.  The scale factor
  405.        is apparently equal to the point size.  It isn't well-documented. */
  406.  
  407.     vdevice.hheight=size*(fm->ascender-fm->descender);
  408.  
  409.     /* with this li'l loop we can handle var-width fonts but they look
  410.        ugly. Stick to Courier & Ohlfs if you can. */
  411.     for(i=0;i<MIN(fm->widthsLength,256);i++) {
  412.       float w=fm->widths[i];
  413.       if (w>wmax) wmax=w;
  414.       };
  415.     vdevice.hwidth=size*wmax;
  416.     return 1;
  417.     }
  418.   else
  419.     return 0;
  420. }
  421.  
  422. /* 
  423.  * NeXT_char (outputs one char)
  424.  */
  425. int NeXT_char(char c)
  426. {
  427.   char    s[2];
  428.  
  429.   s[0] = c; s[1]='\0';
  430.   PSmoveto(vdevice.cpVx,vdevice.cpVy);
  431.   PSshow(s);
  432.   if (vdevice.sync)
  433.       NXPing();
  434. }
  435.  
  436. /*
  437.  * NeXT_string
  438.  *
  439.  *    Display a string at the current drawing position.
  440.  */
  441. int NeXT_string(char s[])
  442. {
  443.   PSmoveto(vdevice.cpVx,vdevice.cpVy);
  444.   PSshow(s);
  445.   NXPing();
  446. }
  447.  
  448. /*
  449.  * NeXT_fill
  450.  *
  451.  *    fill a polygon
  452.  */
  453. int NeXT_fill(
  454.   int n,
  455.   int x[],
  456.   int y[])
  457. {
  458.   int    i;
  459.   PSnewpath();
  460.   PSmoveto(x[0],y[0]);
  461.   for(i=1;i<n;i++) PSlineto(x[i],y[i]);
  462.   PSclosepath();
  463.   PSfill();
  464.   if (vdevice.sync)
  465.       NXPing();
  466. }
  467.  
  468. /*
  469.  * NeXT_backbuf
  470.  *
  471.  *    Set up double buffering by allocating the back buffer and
  472.  *    setting drawing into it.
  473.  */
  474. int NeXT_backbuf(void)
  475. {
  476.   NXRect r;
  477.   [drawable unlockFocus];
  478.   [view getBounds:&r];
  479.   backbuf = [[NXImage alloc] initSize:&r.size];
  480.   if (![backbuf useCacheWithDepth:NX_TwentyFourBitRGBDepth]) {
  481.     fprintf(stderr,"couldn't create backing buffer.\n");
  482.     return 0;
  483.     };
  484.   drawable = backbuf;
  485.   [drawable lockFocus];
  486.   back_used = 1;
  487.   return(1);
  488. }
  489.  
  490. /*
  491.  * NeXT_swapbuf
  492.  *
  493.  *    Swap the back and front buffers. (Really, just copy the
  494.  *    back buffer to the screen).
  495.  */
  496. int NeXT_swapbuf(void)
  497. {
  498.   NXPoint origin = {0,0};
  499.   [drawable unlockFocus];
  500.   [view lockFocus];
  501.   [backbuf composite:NX_COPY toPoint:&origin];
  502.   [winder flushWindow];
  503.   [view unlockFocus];
  504.   [drawable lockFocus];
  505. }
  506.  
  507. /*
  508.  * NeXT_frontbuf
  509.  *
  510.  *    Make sure we draw to the screen.
  511.  */
  512. int NeXT_frontbuf(void)
  513. {
  514.   [drawable unlockFocus];
  515.   drawable = view;
  516.   [drawable lockFocus];
  517. }
  518.  
  519. /*
  520.  * Syncronise the display with what we think has been sent to it...
  521.  */
  522. int NeXT_sync(void)
  523. {
  524.     NXPing();
  525. }
  526.  
  527. int NeXT_setls(int ls)
  528. {
  529. }
  530.  
  531. int NeXT_setlw(int w)
  532. {
  533. }
  534.  
  535. /*
  536.  * the device entry
  537.  */
  538. static DevEntry NeXTdev = {
  539.     "NeXT",
  540.     "small",
  541.     "large",
  542.     NeXT_backbuf,
  543.     NeXT_char,
  544.     NeXT_checkkey,
  545.     NeXT_clear,
  546.     NeXT_color,
  547.     NeXT_draw,
  548.     NeXT_exit,
  549.     NeXT_fill,
  550.     NeXT_font,
  551.     NeXT_frontbuf,
  552.     NeXT_getkey,
  553.     NeXT_init,
  554.     NeXT_locator,
  555.     NeXT_mapcolor,
  556.     NeXT_setls,
  557.     NeXT_setlw,
  558.     NeXT_string,
  559.     NeXT_swapbuf, 
  560.     NeXT_sync
  561. };
  562.  
  563. /*
  564.  * _NeXT_devcpy
  565.  *
  566.  *    copy the NeXT device into vdevice.dev.
  567.  */
  568. int _NeXT_devcpy(void)
  569. {
  570.     vdevice.dev = NeXTdev;
  571. }
  572.